home *** CD-ROM | disk | FTP | other *** search
- 3-1
-
- The Generic Adventure Game System
- Copyright 1985, 1986 by Mark J. Welch 415-845-2430 (voice)
-
-
- The GAGS source code (briefly explained, not included)
- --------------------
-
- [ The GAGS source code is available to registered users of GAGS
- for $25; source code purchasers must also sign an agreement not
- to distribute or share the source code. For information,
- contact Mark J. Welch, P.O.Box 2409, SF, CA 94126.]
-
- The Generic Adventure Game System is broken into fourteen
- "modules," each structured as a Turbo Pascal "include" file.
- Initially, the entire program was in one source code file. The
- tremendous size of the parser led to its being broken out as a
- separate module. Soon, other groups of procedures were also
- removed from the main program file so that I could edit and print
- smaller pieces at a time, and so that Turbo could handle the
- files (Turbo Pascal can only process files up to 64K).
- As my Programming Methodology professor pointed out four
- years ago, it is also much easier to track down bugs when you
- only modify one module at a time. Naturally, I should've started
- the project by defining the separate modules, and I should have
- drawn out pseudo-code, so that the program was better structured.
- These bad habits might explain the 'C' I got in that class....
-
- The twelve modules are:
-
- -- the parser (PARSE.MOD);
- -- the execution module (EXECUTE.MOD) which interprets the
- user's parsed command line, with three sub-modules EXECSUBS.MOD,
- SPECIALS.MOD, and SAVEREST.MOD;
- -- the initialization module (INIT.MOD), which zeros out all
- the arrays and reads the data file;
- -- the declaration module (DECLARE.MOD), which contains all the
- global type, constant, and variable declarations;
- -- a command-line parameter checking module (PARAM.MOD);
- -- a title-printing module (TITLE.MOD) which also contains
- several useful tools;
- -- a creature-animation module (ANIMATE.MOD), which executes
- any actions creatures take (i.e. attacking the player);
- -- two tools modules (GENTOOLS.MOD and SPCTOOLS.MOD) which contain
- procedures and functions used by more than one other module;
- -- a module to describe and list the player's location
- information (DESCRIBE.MOD);
- -- and the main program (ADVENT.PAS) which INCLUDEs the other
- modules.
-
- 3-2
-
- Summary:
-
- The parser is quite straightforward: it takes a command line
- string, and breaks it into words; it massages the words, tries to
- eliminate unimportant words, throws away adjectives if they match
- following nouns, and locate from one to four important sentence
- elements: a verb, a noun, a preposition, and an object of the
- preposition. These are passed back to the main program.
- The main program immediately 'executes' the user's
- deciphered command (unless a syntax error was discovered in the
- parser); the execute module simply decides which verb was used
- and calls the procedure appropriate to that verb or class of
- verbs.
-
- Whenever a change is made to the program, several modules
- must usually be changed. For example, to add a new field to nouns
- (say, 'NUKEABLE'), the declaration of the nouns record must be
- changed to add the field; the initialization procedure must
- assign it a default value ('true'?) and must also check to see if
- the noun declaration in the data file changes its 'default'
- value; and any appropriate changes must also be made to the
- execute module. In this case, the logical intent would be to also
- add a verb 'NUKE' and of course also add a procedure in the
- execute module called 'nuke' with a parameter of what noun to
- destroy. That verb would have to be added in the initialization
- module (INIT_VERBS procedure) so the parser recognizes it; and an
- appropriate check would be made in the nuke procedure to see if
- conditions are met. Nuke might activate a special, which means
- the nuke procedure would call the 'special' procedure if the
- proper conditions are met.
-
-
- Mark J. Welch
- P.O. Box 2409
- San Francisco CA 94126
- (415) 845-2430 (voice)
-
- 3-3
-
- GAGS - A Generic Adventure Game System
- Copyright 1985, 1986 by Mark Welch
-
- --------------------------
- In More Detail: The Parser
- --------------------------
- Definition: The PARSER examines each word in an input sentence
- to determine whether it is a valid part of speech in the context of
- other words in the sentence.
-
-
- Background:
- In some software, the input is quite fixed. In spreadsheets or
- word processors, for example, a fixed list of commands are
- available, and no general flexibility is permitted (although
- multiple ways might be offered to accomplish the same task).
- In some early adventure games, two-word commands were the
- limit. "TAKE BOOK" was the way you picked up a book. Sometimes
- synonyms were offered ("GET", for example). More complex sentences
- were sometimes permitted ("THROW AXE AT DWARF"), but it's a much
- easier programming task if the syntax is fixed. For this last
- reason, the word "the" was a latecomer to adventure games.
- Of course, what you really want is a way to say "Take the
- small red key from the second dwarf and put it in the blue box
- under the rug" and have the program figure out what you want. GAGS
- can't do that, for several reasons. It can, however, accept some
- fairly long sentences and concepts more complex than "THROW AXE."
- One acquaintance suggested that a really good adventure game
- should understand a sentence like "Dive under the fallen branch and
- roll to the left, grabbing the laser pistol as you rise, and sever
- the dwarf's leg by ricocheting a laser shot off of the pickup's
- mirror." I'll leave that as an exercise to the reader.
-
- What does a parser need to do?
-
- A parser breaks up a sentence into parts of speech. Let's
- think about that for a minute, using the previous sentence as an
- example.
-
- "A parser breaks up a sentence into parts of speech."
- / | | | | |
- article/ subject^ ^verb ^object ^prep ^obj.of prep
-
- Instantly, most people can recognize the subject and the verb.
- "Parser" is the noun, and "breaks up" is the verb. Or is "breaks"
- the verb? "Up" is a preposition...but here it's an adverb. Gee, the
- English language is complicated.
- Already we have a problem: some words can serve as multiple
- parts of speech and can only be parsed by checking context. There
- are rules to English, but they're complex and filled with
- exceptions. Many programmers are working hard to develop "Natural
- Language Interfaces" to computers, so people can get computers to
- perform complex tasks without having to know how to program a
- computer. Very few of those "natural language interfaces" can
- accept a complex sentence, and most -- like GAGS' parser -- limit
- their knowledge to a certain task so context problems are reduced
- and the rules can be made more limited.
-
- (continued)
-
- 3-4
-
- (the parser, continued)
-
-
- In writing this game, I wasn't interested in AI or complex English
- or anything like that. I just wanted to allow people to enter
- understandable sentences, like "put the red key with the blue globe." How
- to do that?
- I cheated, to start. The first thing my parser does is strip
- out extraneous words, words that always (I hope) add no real
- meaning to a sentence. "The" and "a" are removed. So is "go", since
- that has no meaning unless it's followed by a direction. GAGS wants
- a verb to come first in the sentence, and will choke if there isn't
- one.
-
-
-
- GAGS' Parser
- ------------
- The Parse procedure first breaks the sentence up into words
- (an array of strings), arbitrarily counting any non-alphabetic
- character as a word separator. (Actually, the real check is for
- ASCII characters from 'A'..'z'.)
- It then strips out any words which are "extras." A strange
- effect is that no check is made to see if the sentence really made
- sense before it was "stripped" of extra words. The sentence
-
- "The Put the the red the gun the in the the the wooden the bookcase"
-
- becomes
-
- "Put red gun in wooden bookcase."
-
- The parser then immediately begins scanning the sentence,
- left-to-right. The first word must be a verb now. If it is, the
- program moves on to the next word (or exits when it finds no more
- words). The program expect the second word to be a noun. If it's
- not a noun, it checks to see if it is an adjective with a noun
- following it. If neither is true, it checks the possibility that
- the second word might just be a preposition ("Look in bookcase").
- If the second word wasn't a preposition, the third word is checked
- as a preposition. The following word(s) is/are again checked as a
- noun or an adjective-noun pair.
-
- A more "correct" parser could check for a verb, and then check
- to make sure that any articles ("the" or "a") are positioned
- properly with nouns, and that words like "please" or "now" are
- located logically.
-
- Four strings are returned from the parser: a verb, a noun, a
- preposition, and another noun as the object of the preposition.
- Also, if any error was discovered (a word not recognized, or a
- missing verb), a boolean variable 'syntax_error' is set to 'true.'
-
-
-
-
- 3-5
-
- GAGS - A Generic Adventure Game System
- Copyright 1985, 1986 by Mark Welch
-
- ---------------------------------
- Possible Source Code Enhancements
- ---------------------------------
-
-
-
- Modifying the Source Code: Some Suggestions
- -------------------------------------------
- There are probably an infinite number of ways you can modify
- the source code to GAGS to make it a more enjoyable game. In many
- ways, my original coding was too simple to permit a full-featured
- game. Changes to the game range from relatively simple and painless
- additions to some extremely complex modifications which could mean
- rewriting huge portions of the code. In fact, I'm open-minded
- enough to realize that some efforts would involve rewriting the
- entire game or starting from scratch.
-
-
- Enlarging the Game
- ------------------
- As shipped, GAGS can handle up to 200 rooms, 100 creatures, and
- 100 objects. These limits permit the game to run snugly in a 192K
- IBM PC, or quite comfortably in a 256K system. If you have more
- memory than that, you might want to expand these limits. All the
- changes would be in the declaration module (DECLARE.MOD), where
- you'd need to simply re-define the first and last numbers of each
- range (creatures, rooms, and nouns).
-
-
- "On-Line Help"
- --------------
- One verb you might want to add is "help." A help procedure might
- do one of several things: it might simply read in a file and
- display it on the screen; it might prompt for the user's specific
- help question (or you might patch the parser so the user could
- type "help scream" or whatever); or it might try to offer
- context-sensitive help ("The reason you can't go north is that
- the banshee blocks your way. Banshees often let you pass if you
- give them yogurt").
-
-
- Specials
- --------
- Although several methods of invoking "specials" have been
- provided, you might want to add more by defining new verbs to
- activate them. Or, you might modify the "Take" procedure to
- invoke a special; this would involve a fairly aggressive
- rewriting of that procedure. You might want to modify the
- procedures in which a creature is killed to search for text to
- display, rather than the stock "creature is killed" message; you
- might even want to leave a dead body in the room after a creature
- is killed. Keying user-defined verbs to specials would be ideal.
-
- (continued)
-
- 3-6
-
- (Enhancing GAGS, continued)
-
-
- Adding Verbs
- ------------
- Probably the simplest thing to do is add a verb to the game. In
- the latter stages of development, I was able to add new verbs in
- about ten minutes, plus the time it took to write a procedure to
- execute the verb's desired actions. Adding a verb was designed to
- be the easiest task because I started the game with one verb
- ("Look") and added new verbs at the rate of about one per night
- of development and debugging.
- To add a verb, you must modify the Init_Verbs procedure so
- that the parser recognizes it as a valid verb, and you must add
- the new verb to the multiple if..then..else statement in the
- Execute procedure so that Execute performs the action you desire
- from the verb's invocation.
- If you want to add synonyms, this involves merely calling
- whatever procedure already exists. If you want to create a new
- procedure, you have Execute call it and then write the procedure.
- I added the "Scream" procedure in this way in a total of fifteen
- minutes, and then created two synonyms ("shriek" and "shout") in
- five more minutes. Of course, the Scream procedure doesn't do
- anything to modify variables; more complex procedures will
- involve some fairly complex actions and testing. When you write a
- new procedure, you'll usually want to test to see if the desired
- action can be performed, and whether the things being acted upon
- are present.
- Two verbs called for by several beta-testers but not
- implemented are "shoot" and "fire," which would be useful in
- games with guns.
-
-
- Multiple Nouns with the Same Name
- ---------------------------------
- One thing Infocom adventures provide are multiple nouns with the
- same name, like "brass key" and "bronze key." While GAGS
- currently doesn't provide this, it wouldn't be too difficult to
- modify it to do so. The parser would pass along the noun, but the
- Noun_Number procudure currently returns only the number of the
- first noun with the specified name. You could have Noun_Number
- check to see if the adjective matches (which would involve having
- the parser return the adjective along with the noun, verb,
- preposition, and object) and resolve unanswered ambiguities by
- asking, "Which <noun> do you mean, the <first_adj> one or the
- <second_adj> one?"
- Alternately, the parser could be left to resolve the
- ambiguity and could then return a noun NUMBER instead of the
- actual noun name. This last approach could also save some
- processor time since the noun's number is accessed during both
- the Is_Noun and the Noun_Number functions. Of course, returning a
- noun number instead of a name would require a major rewrite of
- the program.
-
- (continued)
-
- 3-7
-
- (Enhancing GAGS, continued)
-
- Creature Animation
- ------------------
- With a fairly small effort, creatures in the game could be
- "animated" -- that is, made to move from room to room within the
- game. This involves modifying the ANIMATE module by adding new
- procudure(s) and making calls to them from the animate procedure.
- The procedure could check a new field in the creature record and
- thus decide what sort of motion is called for (none, random, or
- intelligent). It might merely have the creature follow the player
- once encountered, or might invoke random behavior. Perhaps
- creatures could pick up items the player has discarded (or thrown
- at the creatures), and even use them as weapons against the
- player or as tools to their own goals. There are some fascinating
- possibilities here.
-
-
- Turn/Time Sensitivity
- ---------------------
- In the same manner -- a module executed from the main program --
- the game could support time or number-of-turn sensitivity. For
- example, the game might seal off an area of the game after a
- certain time, and trap the player inside (or outside). Or a
- creature might be added to the game after a certain time period.
- Perhaps the player could be chased more aggressively by creatures
- as time passes, or even chased at a rate commensurate (sp?) with
- his or her skill level, so experienced adventurers who breeze
- through many rooms quickly are instantly set upon by all the
- beasts available. The player might also collapse from hunger if
- s/he hasn't eaten food in a certain number of turns. Again, the
- limits for this addition are virtually limitless, but all require
- some modification of several procedures.
-
-
- Adding Verbs in Data Files (User-defined verbs)
- --------------------------
- When I first began designing GAGS, I had hoped to allow new verbs
- and their actions to be defined in the data file, so that anyone
- could add new verbs. I decided that although the idea was
- conceptually sound, the difficulty of the task made it not worth
- the advantage. Additionally, an additional level of game design
- complexity would be added.
- I think that permitting "special" verbs to be defined in data
- files is still a possibility, and though not at all a simple
- task, it would not be a lifelong effort. Essentially, my approach
- would be to add a new "special" procedure -- or more than one --
- but leave the verb names undefined. Then, when the data file was
- read in, the verb names could be plugged into place and tested
- against. If the specified conditions of the special were in
- place, and the verb was typed, a standard "special" could be
- executed.
-
-
- 3-8
-
-
- Attempts to reduce the size of GAGS
- ===================================
-
- The program already makes extensive use of overlay files,
- due to Turbo Pascal's 64K code segment limit. I noticed only
- about a 5-second slowdown in the game's initialization when I
- began using overlays. Since the total of the .COM file and the
- overlay files is about 75K, it's probably relatively simple to
- reduce the code size to under 64K and avoid the use of overlays,
- but I don't find a pressing need and prefer not to worry about
- the RAM needed by each feature I add.
-
- Rough minimum size: 59K
- -----------------------
- Before GAGS grew to its present size, in an effort to further
- reduce the RAM needed, I tried adding more overlays in several
- areas. First, the main modules (execute, the two initialize
- procedures, title, and the parser) were overlaid. This, of
- course, means a disk access every turn since the parser and
- execute procedures alternate. Then I overlaid as many of the
- EXECSUBS procedures as possible, breaking them into two or three
- overlays to avoid some disk swapping.
- I then reduced the size of the arrays: to 10 creatures, 25
- nouns, and 70 rooms. This reduced the program's reported maximum
- heap size to 64K exactly.
- I then installed my machine as a 128K IBM PC, and attempted to
- run the object file with varying amounts of memory allocated to a
- print buffer (in 1K increments).
- The program, as quickly overlaid and compressed, will execute
- with a 43K print buffer installed, or in 85K of RAM. The
- operating system reserves 26K of the 85K; the program itself,
- with its data areas and such, thus takes up 59K.
- The main program .COM file was under 20K, as distinct from the
- 51K file generated without use of overlays. However, even with
- all the overlays above, the standard 200-room/100-creature/100-
- noun data would not fit in 128K, so there are no real savings
- except possible space reserved for other resident programs in a
- 192K machine.
- These size figures were obtained before a number of GAGS'
- functions were added or enhanced; GAGS is probably about 10-20%
- larger now than it was then. Reducing GAGS to run in a 64K CP/M
- system is almost impossible, and would certainly involve too much
- performance degradation to be worth the effort.
-
-